package cn.com.libertymutual.core.security.encoder;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.logging.log4j.util.Strings;

/**
 * 用MD5加密字符串,得到MD5字符串为小写
 * 
 * @author LuoGang
 * 
 */
public class MD5Helper {

	/** 十六进制使用的字符,小写 */
	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
			'e', 'f' };

	/** 十六进制使用的字符,大写 */
	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
			'E', 'F' };
	/** 字符串默认使用的编码 */
	public static final String DEFAULT_CHARSET_NAME = "UTF-8";

	/**
	 * MD5加密处理对象
	 * 
	 * @return
	 * @throws Exception 
	 */
	public static MessageDigest getDigest() throws Exception {
		try {
			return MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("当前系统不支持MD5加密!", e);
		}
	}

	/**
	 * 将数据data进行MD5加密
	 * 
	 * @param data
	 * @return
	 */
	public static String encode(final byte[] data) {
		MessageDigest md5 = null;
		try {
			md5 = getDigest();
			return String.valueOf(encodeHex(md5.digest(data)));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// md5.update(data);
		return null;
	}

	/**
	 * 对字符串进行MD5加密
	 * 
	 * @param input 明文
	 * @param charsetName 明文使用的字符集
	 * 
	 * @return 密文
	 */
	public static String encode(String input, String charsetName) {
		byte[] data = null;
		try {
			data = toBytes(input, charsetName);
			
			return encode(data);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return encode(data);
	}

	/**
	 * 使用默认的字符集对明文input进行MD5加密
	 * 
	 * @param input 要加密的明文字符串
	 * @return
	 */
	public static String encode(String input) {
		return encode(input, DEFAULT_CHARSET_NAME);
	}

	/**
	 * 使用charsetName字符集对明文input进行MD5加密
	 * 
	 * @param input 要加密的明文字符串
	 * @param charsetName input使用的字符集
	 * @return
	 */
	public static String md5(String input, String charsetName) {
		return encode(input, charsetName);
	}

	/**
	 * 使用默认的字符集对明文input进行MD5加密
	 * 
	 * @param input 要加密的明文字符串
	 * @return
	 */
	public static String md5(String input) {
		return encode(input, DEFAULT_CHARSET_NAME);
	}

	/**
	 * 将数据data进行MD5加密
	 * 
	 * @param data
	 * @return
	 */
	public static String md5(byte[] data) {
		try {
			return String.valueOf(encodeHex(getDigest().digest(data)));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 字节转换为16进制的字符串
	 * 
	 * @param data
	 * @return
	 */
	protected static char[] encodeHex(byte[] data, char[] toDigits) {
		int l = data.length;
		char[] out = new char[l << 1];

		int i = 0;
		for (int j = 0; i < l; i++) {
			out[(j++)] = toDigits[((0xF0 & data[i]) >>> 4)];
			out[(j++)] = toDigits[(0x0F & data[i])];
		}
		return out;
	}

	/**
	 * 将字节数据转换为16进制的字符串
	 * 
	 * @param data
	 * @param toLowerCase 是否使用小写
	 * @return
	 */
	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}
	
	
	/**
	 * 将字符串input按照指定的编码转换为byte数组
	 * 
	 * @param input 字符串
	 * @param charsetName 使用的编码
	 * @return
	 * @throws Exception 
	 */
	private static byte[] toBytes(String input, String charsetName) throws Exception {
		if( input == null ) {
			return new byte[0];
		}
		byte[] data;
		try {
			data = Strings.isNotBlank(charsetName) ? input.getBytes(charsetName) : input.getBytes();
		} catch (UnsupportedEncodingException e) {
			// data = input.getBytes();
			throw new Exception(e);
		}
		return data;
	}
	/**
	 * 将字节数据转换为16进制的小写字符串
	 * 
	 * @param data
	 * @return
	 */
	public static char[] encodeHex(byte[] data) {
		return encodeHex(data, true);
	}

	public static void main(String[] args) {
		String input = "amount=50.00&branchCode=50&businessNo=9103015007140000037000&businessSource=b2c&businessType=policy&callbackUrl=http://10.132.8.147:7003/ebusiness/b2c/ePayBgReturnAction.do&noticUrl=http://10.132.8.147:7003/ebusiness/b2c/ePayBgNoticeAction.do&property00=张晓航&property01=9103015007140000037000&property02=张晓航&property19=5014120000000081&redirectUrl=http://10.132.8.147:7003/ebusiness/b2c/ePayPageReturnAction.do?actionType=paySuccessv56778ye9s6dwghm88888sd3tvp6axxx";
		// input += "8s0ql59nqt8pz1vk9aclltgg39ji0fv9";
		try {
			System.out.println(md5(input));// .getBytes("UTF-8")));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// System.out.println(DigestUtils.md5Hex(input));
	}
}
